#include "FpsCameraControl.hpp"
#include "Camera.hpp"
#include "Input.hpp"
#include "Engine.hpp"
#include "OpenGL.hpp"
#include "Event.hpp"

using namespace cge;

FpsCameraControl::FpsCameraControl( Input& input, Camera& camera)
: cam_(camera), inp_(input), eng_(input.getEngine()) {
	kw_ = SDLK_w; ks_ = SDLK_s;
	ka_ = SDLK_a; kd_ = SDLK_d;
	dragging_ = false;
	rotSpeed_ = 12.0;
	movSpeed_ = 6.0;
}

void FpsCameraControl::connect() {
	inp_.addInputListener(*this);
	eng_.addTask(*this);
}


void FpsCameraControl::disconnect() {
	eng_.removeTask(*this);
	inp_.removeInputListener(*this);
}

void FpsCameraControl::onMouseMoved( MouseMovedEvent &ev ) {
	if( ev.isConsumed() )
		return;

	if( dragging_ ) {
		vec2 rel = vec2(ev.getX(),ev.getY()) - mc_;
		newAngles_ += rel/1024.0;
		inp_.moveMouse((unsigned)mc_.x, (unsigned)mc_.y);
		ev.consume();
	}
}

void FpsCameraControl::runTask() {
	if( move_.x!=0.0 || move_.y!=0.0 || move_.z!=0.0 ) {
		cam_.getNode().parentTranslate(
			cam_.getNode().getRotation().unrotateVector(move_ * eng_.getFrameDelta())
		);
	}

	double distance = (angles_-newAngles_).normSquared();
	if( distance>=1e-16 ) {
		distance = sqrt(distance);
		double delta    = eng_.getFrameDelta()*rotSpeed_/distance;
		if(delta>=1.0)
			delta = 1.0;
		angles_ = linearInterpolate(angles_,newAngles_,delta);
		cam_.getNode().setRotation(Quaternion(angles_.y,angles_.x,0.0));
	}
}

void FpsCameraControl::onMouseButtonPressed( MouseButtonEvent &ev ) {
	if( ev.isConsumed() )
		return;
	if( ev.getButton() == SDL_BUTTON_LEFT ) {
		dragging_ = true;
		inp_.setCursorVisible(false);
		mc_.set(ev.getX(),ev.getY());
		ev.consume();
	}
}

void FpsCameraControl::onMouseButtonReleased( MouseButtonEvent &ev ) {
	if( ev.getButton() == SDL_BUTTON_LEFT ) {
		dragging_ = false;
		inp_.setCursorVisible(true);
	}
}

void FpsCameraControl::onKeyPressed( KeyEvent &ev ) {
	if( ev.isConsumed() )
		return;

	bool consume = true;

	if( ev.getCode() == kw_ )
		move_.z = -movSpeed_;
	else if( ev.getCode() == ks_ )
		move_.z = movSpeed_;
	else if( ev.getCode() == ka_ )
		move_.x = -movSpeed_;
	else if( ev.getCode() == kd_ )
		move_.x = movSpeed_;
	else
		consume = false;

	if( consume )
		ev.consume();
}

void FpsCameraControl::onKeyReleased( KeyEvent &ev ) {
	bool consume = true;

	if( ev.getCode() == kw_  || ev.getCode() == ks_ )
		move_.z = 0.0;
	else if( ev.getCode() == ka_ || ev.getCode() == kd_ )
		move_.x = 0.0;
	else
		consume = false;

	if( consume )
		ev.consume();
}